#ifndef HANDLEFACTORY_OBJECTDELETERIMPL_H
#define HANDLEFACTORY_OBJECTDELETERIMPL_H

///////////////////////////////////////////////////////////////////////////////
//
// HandleImpl.h
//
///////////////////////////////////////////////////////////////////////////////
//
// Author:            Jan Maes
// Created:           Sunday, June 15, 2008
// Responsibilities:  Implementation of the Handle class
// Usage:             Only to be called from Handle
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// namespace HandleFactory
///////////////////////////////////////////////////////////////////////////////

namespace HandleFactory
  {

  ///////////////////////////////////////////////////////////////////////////////
  // class HandleImplBase
  ///////////////////////////////////////////////////////////////////////////////

  template <class TObject>
  class HandleImplBase
    {
    public:
      
      HandleImplBase(TObject* ip_object) : m_counter(1), mp_object(ip_object)
        {
        }

      ///////////////////////////////////////////////////////////////////////////////

      virtual ~HandleImplBase() throw()
        {
        }

      ///////////////////////////////////////////////////////////////////////////////

      virtual void DeleteObject() = 0;

      ///////////////////////////////////////////////////////////////////////////////

      void RefIncrement() throw()
        {
        ++m_counter;
        }

      ///////////////////////////////////////////////////////////////////////////////

      void RefDecrement() throw()
        {
        --m_counter;
        }

      ///////////////////////////////////////////////////////////////////////////////

      unsigned long GetRefCount() const throw()
        {
        return m_counter;
        }

      ///////////////////////////////////////////////////////////////////////////////

      TObject* GetInternalObject() throw()
        {
        return mp_object;
        }

      ///////////////////////////////////////////////////////////////////////////////

      bool IsValid() const throw()
        {
        return (mp_object != 0);
        }

      ///////////////////////////////////////////////////////////////////////////////

    private:

      HandleImplBase(const HandleImplBase& i_other);

      ///////////////////////////////////////////////////////////////////////////////

      HandleImplBase& operator = (const HandleImplBase& i_other);

      ///////////////////////////////////////////////////////////////////////////////

    private:
      unsigned long m_counter;
      TObject*      mp_object;
    };

  ///////////////////////////////////////////////////////////////////////////////
  // class HandleImpl_default_delete
  ///////////////////////////////////////////////////////////////////////////////

  template <class TObject>
  class HandleImpl_default_delete : public HandleImplBase<TObject>
    {
    public:

      HandleImpl_default_delete(TObject* ip_object) : HandleImplBase(ip_object)
        {
        }

      ///////////////////////////////////////////////////////////////////////////////

      virtual ~HandleImpl_default_delete() throw()
        {
        }

      ///////////////////////////////////////////////////////////////////////////////

      virtual void DeleteObject() throw()
        {
        if (IsValid())
          delete GetInternalObject();
        }

      ///////////////////////////////////////////////////////////////////////////////
    };

  ///////////////////////////////////////////////////////////////////////////////
  // class HandleImpl_custom_delete
  ///////////////////////////////////////////////////////////////////////////////

  template <class TObject, class TDeleter>
  class HandleImpl_custom_delete : public HandleImplBase<TObject>
    {
    private:
      TDeleter m_deleter;

    public:

      HandleImpl_custom_delete(TObject* ip_object, TDeleter i_deleter) : 
        HandleImplBase(ip_object), m_deleter(i_deleter) 
        {
        }

      ///////////////////////////////////////////////////////////////////////////////

      virtual ~HandleImpl_custom_delete() throw()
        {
        }

      ///////////////////////////////////////////////////////////////////////////////

      virtual void DeleteObject()
        {
        if (IsValid())
          m_deleter(GetInternalObject());
        }

      ///////////////////////////////////////////////////////////////////////////////

    };

  ///////////////////////////////////////////////////////////////////////////////
  // class HandleImpl_no_delete
  ///////////////////////////////////////////////////////////////////////////////

  template <class TObject>
  class HandleImpl_no_delete : public HandleImplBase<TObject>
    {

    public:

      HandleImpl_no_delete() : 
        HandleImplBase(0)
        {
        }

      ///////////////////////////////////////////////////////////////////////////////

      virtual ~HandleImpl_no_delete() throw()
        {
        }

      ///////////////////////////////////////////////////////////////////////////////

      virtual void DeleteObject() throw()
        {
        }

      ///////////////////////////////////////////////////////////////////////////////

    };

  } // namespace HandleFactory

#endif